package com.xishu.service;

import com.xishu.client.ZkClient;
import com.xishu.entity.AbstractEntity;
import com.xishu.util.Tools;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessSemaphoreMutex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class DistributeLockService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(DistributeLockService.class);

    private static DistributeLockService instance = new DistributeLockService();

    private Map<String, Object> lockMap = new ConcurrentHashMap<>();

    public DistributeLockService() {
    }

    public static DistributeLockService getInstance() {
        return instance;
    }

    public InterProcessLock tryLock(String lockKey) throws Exception {
        long startTime = System.currentTimeMillis();
        logger.info("start get lock {} time {}", lockKey, System.currentTimeMillis());

        if (!lockKey.startsWith("/")) {
            lockKey = "/" + lockKey;
        }

        //分布式锁
        CuratorFramework client = ZkClient.getInstance().getClient();
//            CuratorFramework client = ZkClient.getInstance().createClient();
        InterProcessSemaphoreMutex lock = new InterProcessSemaphoreMutex(client, lockKey);
        lock.acquire(60, TimeUnit.SECONDS);
        logger.info("get the lock, {}, cost time {}", lockKey, System.currentTimeMillis() - startTime);

        return lock;

    }

    /**
     * 获取锁
     *
     * @param t
     * @throws InterruptedException
     */
    public InterProcessLock tryLock(AbstractEntity t) throws Exception {
        String lockKey = getEntityKey(t);
        return tryLock(lockKey);
    }

    /**
     * 释放锁
     */
    public void releaseLock(InterProcessLock lock) {
        logger.info("release lock key {}");

        //分布式锁
        try {
            lock.release();
        } catch (Exception e) {
            logger.error("e", e);
        }
    }


}
